package cloudRemoteService

import (
	"encoding/json"
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-common/commLogger"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/HttpClient"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Json"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Method"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Number"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/String"
	"go-fox-edge-kernel-manager/component"
	"net/http"
	"sync"
	"time"
)

var (
	mutex         sync.Mutex
	header        map[string]string
	username      string
	password      string
	host          string
	lockdown      int64
	loginLastTime int64
)

func init() {
	header = make(map[string]string)
}

func IsLockdown() bool {
	mutex.Lock()
	defer mutex.Unlock()
	return loginLastTime+lockdown*1000 > time.Now().UnixMilli()
}

func IsLogin() bool {
	mutex.Lock()
	defer mutex.Unlock()

	return len(header) != 0
}

func Login() error {
	mutex.Lock()
	defer mutex.Unlock()

	return login()
}

func login() error {
	// 获得账号/密码
	valueConfig, err := component.ManageConfigService.GetConfigValueThis("repositoryConfig")
	if err != nil {
		return err
	}
	if len(valueConfig) == 0 {
		return errors.New("登录云端服务器：从Redis配置中获得账号/密码失败！")
	}

	// 取出信息
	host = Map.GetString(valueConfig, "host", "http://localhost:8080")
	username = Map.GetString(valueConfig, "username", "username")
	password = Map.GetString(valueConfig, "password", "")
	lockdown = Map.GetInt64(valueConfig, "lockdown", 60)

	request := make(map[string]interface{})
	request["username"] = username
	request["password"] = password

	// 不用产生后台日志：这个自动操作，会产生太多的垃圾数据
	commLogger.Console.Info("登录云端服务器：开始登录！")

	// 发送请求
	str, err := HttpClient.POST(host+"/auth/login", request, nil)
	if err != nil {
		loginLastTime = time.Now().UnixMilli()
		commLogger.Console.Error("登录云端服务器：登录失敗！ " + host + "  ," + err.Error())
		return err
	}

	// 解码返回的数据
	var respond map[string]interface{}
	err = json.Unmarshal([]byte(str), &respond)
	if err != nil {
		loginLastTime = time.Now().UnixMilli()
		commLogger.Console.Error("登录云端服务器：登录失敗！ " + host + "  ," + err.Error())
		return err
	}

	// 检查：是否登录成功
	code := respond["code"]
	message := respond["msg"]
	if http.StatusOK != Number.MakeInt(code) {
		loginLastTime = time.Now().UnixMilli()
		commLogger.Console.Error("登录云端服务器：登录失败！ " + host + "  ," + message.(string))
		return errors.New(message.(string))
	}

	// 提取token
	token, err := Map.GetValue(respond, "data", "access_token")
	if err != nil || Method.HasEmpty(token) {
		message = "云端返回的token异常"
		loginLastTime = time.Now().UnixMilli()
		commLogger.Console.Error(message)
		return errors.New(message.(string))
	}

	// 保存token，方便后面反复使用
	header["Authorization"] = "Bearer " + token.(string)

	commLogger.Console.Info("登录云端服务器：登录成功！")

	return nil

}

func ExecutePost(res string, body interface{}) (map[string]interface{}, error) {
	mutex.Lock()
	defer mutex.Unlock()

	return executePost(res, Json.BuildJson(body))
}

func executePost(res string, body interface{}) (map[string]interface{}, error) {
	// 先尝试执行：可能账号过期而被拒绝
	respondVO, _ := executePostTry(res, body)

	// 检查：是否登录成功
	code := respondVO["code"]

	// 检查：登录是否已经失效
	if http.StatusUnauthorized == Number.MakeInt(code) {
		// 清空上次登录的信息
		header = make(map[string]string)

		// 此时，再尝试自动登录并执行一次，
		respondVO, err := executePostTry(res, body)
		if err != nil {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:code=" + String.ToString(code) + "失败:message=" + String.ToString(respondVO["msg"]))
		}

		if http.StatusOK != Number.MakeInt(respondVO["code"]) {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:code=" + String.ToString(code) + "失败:message=" + String.ToString(respondVO["msg"]))
		}

		return respondVO, nil
	} else {
		if http.StatusOK != Number.MakeInt(code) {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:" + Json.BuildJson(respondVO))
		}

		return respondVO, nil
	}
}

func executePostTry(res string, body interface{}) (map[string]interface{}, error) {
	// 检查：是否未登录
	if len(header) == 0 {
		err := login()
		if err != nil {
			return nil, err
		}
	}

	// 检查有没有获得登录成功后的云端令牌
	if len(header) == 0 {
		return nil, errors.New("未登录到云端！")
	}

	// 发送请求
	jsn, err := HttpClient.POST(host+res, body, header)
	if err != nil {
		return nil, err
	}

	// JSON解码
	var data map[string]interface{}
	err = json.Unmarshal([]byte(jsn), &data)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func ExecuteGet(res string, queryParams map[string]interface{}) (map[string]interface{}, error) {
	mutex.Lock()
	defer mutex.Unlock()

	str := ""
	for k, v := range queryParams {
		str += k + "=" + String.ToString(v) + "&"
	}

	if len(str) > 0 {
		str = str[0 : len(str)-1]
	}

	return executeGet(res, str)
}

func executeGet(res, queryParams string) (map[string]interface{}, error) {
	// 先尝试执行：可能账号过期而被拒绝
	respondVO, _ := executeGetTry(res, queryParams)

	// 检查：是否登录成功
	code := respondVO["code"]

	// 检查：登录是否已经失效
	if http.StatusUnauthorized == code {
		// 清空上次登录的信息
		header = make(map[string]string)

		// 此时，再尝试自动登录并执行一次，
		respondVO, err := executeGetTry(res, queryParams)
		if err != nil {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:code=" + String.ToString(code) + "失败:message=" + String.ToString(respondVO["msg"]))
		}

		if http.StatusOK != Number.MakeInt(respondVO["code"]) {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:code=" + String.ToString(code) + "失败:message=" + String.ToString(respondVO["msg"]))
		}

		return respondVO, nil
	} else {
		if http.StatusOK != Number.MakeInt(code) {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:" + Json.BuildJson(respondVO))
		}

		return respondVO, nil
	}
}

func executeGetTry(res, queryParams string) (map[string]interface{}, error) {
	// 检查：是否未登录
	if len(header) == 0 {
		// 尝试登录，出错也无所谓
		err := login()
		if err != nil {
		}
	}

	// 检查有没有获得登录成功后的云端令牌
	if len(header) == 0 {
		return nil, errors.New("未登录到云端！")
	}

	// 发送请求
	jsn, err := HttpClient.GET(host+res, queryParams, header)
	if err != nil {
		return nil, err
	}

	// JSON解码
	var data map[string]interface{}
	err = json.Unmarshal([]byte(jsn), &data)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func ExecuteUpload(res string, filePath string, formData map[string]string) (map[string]interface{}, error) {
	// 先尝试执行：可能账号过期而被拒绝
	respondVO, _ := executeUploadTry(res, filePath, formData)

	// 检查：是否登录成功
	code := respondVO["code"]

	// 检查：登录是否已经失效
	if http.StatusUnauthorized == code {
		// 清空上次登录的信息
		header = make(map[string]string)

		// 此时，再尝试自动登录并执行一次，
		respondVO, err := executeUploadTry(res, filePath, formData)
		if err != nil {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:code=" + String.ToString(code) + "失败:message=" + String.ToString(respondVO["msg"]))
		}

		if http.StatusOK != Number.MakeInt(respondVO["code"]) {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:code=" + String.ToString(code) + "失败:message=" + String.ToString(respondVO["msg"]))
		}

		return respondVO, nil
	} else {
		if http.StatusOK != Number.MakeInt(code) {
			return nil, errors.New("发送数据到云端：" + host + res + "失败:" + Json.BuildJson(respondVO))
		}

		return respondVO, nil
	}
}

func executeUploadTry(res string, filePath string, formData map[string]string) (map[string]interface{}, error) {
	// 检查：是否未登录
	if len(header) == 0 {
		err := login()
		if err != nil {
			return nil, err
		}
	}

	// 检查有没有获得登录成功后的云端令牌
	if len(header) == 0 {
		return nil, errors.New("未登录到云端！")
	}

	// 发送请求
	jsn, err := HttpClient.UPLOAD(host+res, "file", filePath, formData, header)
	if err != nil {
		return nil, err
	}

	// JSON解码
	var data map[string]interface{}
	err = json.Unmarshal([]byte(jsn), &data)
	if err != nil {
		return nil, err
	}

	return data, nil
}
